package gamelogic

import (
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/mysock"
	"server_cluster/common/protoc/pb"
	"server_cluster/logic/game_config"
	"server_cluster/logic/sharemem"
	"slices"
)

//======消息协议处理=====

func GetGachaInfoReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_GetGachaInfoReq, new(pb.CS_GetGachaInfoReq), buf, user).(*pb.CS_GetGachaInfoReq)
	if !ok {
		return config.PROTO_ERROR
	}
	_ = req

	return SendMsg(config.SC_GetGachaInfoRsp, &pb.SC_GetGachaInfoRsp{RetCode: config.OK, GachaInfoList: user.PacketGachaInfoList()}, buf, user)
}

func DoGachaReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_DoGachaReq, new(pb.CS_DoGachaReq), buf, user).(*pb.CS_DoGachaReq)
	if !ok {
		return config.PROTO_ERROR
	}

	if !game_config.GetConfig().DevEnv && req.DebugProbTest {
		return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.SERVER_ERROR}, buf, user)
	}
	gachaConfig := gdconf.GetConfigGacha(req.GachaScheduleId)
	if gachaConfig == nil {
		logger.Error("get gacha config is nil, id: %v", req.GachaScheduleId)
		return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.CONFIG_NOT_FOUND}, buf, user)
	}
	gachaPool := user.UserGacha.GetGachaPool(req.GachaScheduleId)
	if !req.DebugProbTest {
		if req.GachaTimes > user.GetWeaponRemainCellNum() {
			logger.Error("weaponRemainCell not enough, uid: %v", user.GetUid())
			return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.STORE_CAP_MAX}, buf, user)
		}
		if gachaConfig.BeginTime != nil && sharemem.MyShm.TimeNow < gachaConfig.BeginTime.Unix() {
			logger.Error("gacha pool time not arrival, uid: %v", user.GetUid())
			return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.ACTIVE_TIMEOUT}, buf, user)
		}
		if gachaConfig.EndTime != nil && sharemem.MyShm.TimeNow > gachaConfig.EndTime.Unix() {
			logger.Error("gacha pool time already over, uid: %v", user.GetUid())
			return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.ACTIVE_TIMEOUT}, buf, user)
		}
		if gachaConfig.GachaTimesLimit != 0 && gachaPool.TotalGachaCount >= gachaConfig.GachaTimesLimit {
			logger.Error("gacha pool times limit, uid: %v", user.GetUid())
			return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.SERVER_ERROR}, buf, user)
		}
		var itemMap = map[int32]int32{gachaConfig.CostItem: req.GachaTimes}
		if req.GachaTimes == 10 && gachaConfig.TenCostItemCount != 0 && gachaPool.TotalGachaCount < (gachaConfig.TenCostItemCountNum*10) {
			itemMap = map[int32]int32{gachaConfig.CostItem: gachaConfig.TenCostItemCount}
		}
		var itemNum = user.GetItemCount(gachaConfig.CostItem)
		var sub = itemMap[gachaConfig.CostItem] - itemNum
		if sub > 0 {
			itemMap[gachaConfig.CostItem] = itemNum
			itemMap[gdconf.ITEM_GEM] = sub * gachaConfig.DiamondsNum
		}
		ok := CostItems(itemMap, user)
		if !ok {
			logger.Error("add item error, uid: %v", user.GetUid())
			return SendMsg(config.SC_DoGachaRsp, &pb.SC_DoGachaRsp{RetCode: config.ITEM_NOT_ENOUGH}, buf, user)
		}
	}

	itemMap := make(map[int32]int32)
	gachaItemList := make([]*pb.GachaItem, 0)
	for i := int32(0); i < req.GachaTimes; i++ {
		ok, itemId := user.DoGacha(req.GachaScheduleId, req.DebugProbTest)
		if !ok {
			continue
		}
		itemConfig := gdconf.GetItemConfig(itemId)
		if itemConfig == nil {
			continue
		}
		isNewRole := false
		role := user.GetRoleById(itemId)
		if itemConfig.Type == gdconf.ITEM_TYPE_ROLE && role == nil {
			isNewRole = true
		}
		gachaItemList = append(gachaItemList, &pb.GachaItem{
			ItemId:    itemId,
			Type:      itemConfig.Type,
			Quality:   itemConfig.Rarity,
			IsNewRole: isNewRole,
		})
		if !req.DebugProbTest {
			itemMap[itemId] += 1
			itemMap[gachaConfig.GachaConvItem.ItemId] += gachaConfig.GachaConvItem.ItemCount
		}
	}
	if !req.DebugProbTest {
		ret := AddItems(itemMap, user)
		if ret != config.OK {
			logger.Error("add item error, ret: %v, uid: %v", ret, user.GetUid())
		}
	}
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_GACHA_COUNT, true, req.GachaTimes)
	return SendMsg(config.SC_DoGachaRsp,
		&pb.SC_DoGachaRsp{RetCode: config.OK,
			GachaInfoList: user.PacketGachaInfoList(),
			GachaItemList: gachaItemList},
		buf, user)
}

func GachaWishReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_GachaWishReq, new(pb.CS_GachaWishReq), buf, user).(*pb.CS_GachaWishReq)
	if !ok {
		return config.PROTO_ERROR
	}

	gachaConfig := gdconf.GetConfigGacha(req.GachaScheduleId)
	if gachaConfig == nil {
		logger.Error("get gacha config is nil, id: %v", req.GachaScheduleId)
		return SendMsg(config.SC_GachaWishRsp, &pb.SC_GachaWishRsp{RetCode: config.CONFIG_NOT_FOUND}, buf, user)
	}
	if len(req.WishItemIdList) != 0 && len(req.WishItemIdList) != int(gachaConfig.WishItemNum) {
		logger.Error("gacha wish item num not match with config, num: %v, uid: %v", len(req.WishItemIdList), user.GetUid())
		return SendMsg(config.SC_GachaWishRsp, &pb.SC_GachaWishRsp{RetCode: config.SERVER_ERROR}, buf, user)
	}
	//if gachaPool.IsWishTriggered == 1 {
	//	logger.Error("get gachaPool IsWishTriggered, id: %v, uid: %v", req.GachaScheduleId, user.GetUid())
	//	return SendMsg(config.SC_GachaWishRsp, &pb.SC_GachaWishRsp{RetCode: config.WISH_HAD_TRIGGERED}, buf, user)
	//}
	for _, wishItemId := range req.WishItemIdList {
		if !slices.Contains[[]int32, int32](gachaConfig.WishItemIdList, wishItemId) {
			logger.Error("gacha wish item id not match with config, id: %v, uid: %v", wishItemId, user.GetUid())
			return SendMsg(config.SC_GachaWishRsp, &pb.SC_GachaWishRsp{RetCode: config.SERVER_ERROR}, buf, user)
		}
	}
	gachaPool := user.UserGacha.GetGachaPool(req.GachaScheduleId)
	gachaPool.SetWishItemIdList(req.WishItemIdList)

	return SendMsg(config.SC_GachaWishRsp, &pb.SC_GachaWishRsp{RetCode: config.OK, GachaInfo: user.PacketGachaInfo(req.GachaScheduleId)}, buf, user)
}

func GachaHistoryReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_GachaHistoryReq, new(pb.CS_GachaHistoryReq), buf, user).(*pb.CS_GachaHistoryReq)
	if !ok {
		return config.PROTO_ERROR
	}
	_ = req

	history := make([]*pb.GachaHistory, 0)
	for _, gachaPool := range user.UserGacha.GetGachaPoolList() {
		for _, gachaHistory := range gachaPool.GetGachaHistoryList() {
			history = append(history, &pb.GachaHistory{
				GachaScheduleId: gachaPool.ScheduleId,
				ItemId:          gachaHistory.ItemId,
				Timestamp:       gachaHistory.Timestamp,
			})
		}
	}

	return SendMsg(config.SC_GachaHistoryRsp, &pb.SC_GachaHistoryRsp{RetCode: config.OK, History: history}, buf, user)
}
